Amazon GuardDutyをbacklogに連携する
Amazon GuardDutyの通知をみなさんはどうされていますか?色々な通知方法がある中から、Backlogに連携する方法をご紹介します。Backlogへの連携はAWS Lambdaを使い、LambdaのデプロイにはServerless Frameworkを使います。
Backlogに通知し、担当者をアサインし対応内容を記載する
GuardDutyはセキュリティに関する脅威を検出するサービスです。GuardDutyで発生するイベントには、誤検知もありえます。私は普段東京オフィスからAWSコンソールを触っていますが、札幌オフィスに出張しAWSコンソールにログインすると、おそらくGuardDutyのイベントが発生します。普段とは異なるIPアドレスから接続することで検知されることは正常であるものの、実務的には誤検知になります。GuardDutyのイベントが誤検知か判断するために、なんらかの方法で通知を受け取り、担当者が判断する必要があります。backlogを利用すると、対応前/対応中/完了などのステータスを設定できたり、担当者をアサインできます。
backlog設定
backlogの設定と確認を行います。後ほど作成するLambdaでは、APIキーやスペースIDなどを使って課題を投稿します。
APIキーの発行
"個人設定">"API">"登録"から、APIキーを発行します。
スペースIDの確認
backlogのURLの一部(https://[スペースID].backlog.jp
)がスペースIDになっています。
プロジェクトIDの確認
backlogのプロジェクト設定を開くとURLに、「project.id=12345」といった形で表示されます。
課題の作成とIDの確認
backlogのプロジェクト設定>種別>種別の追加から、「GuardDuty通知」のような種類を追加します。追加した種別を選択すると、「issueType.id=123456」といった形で表示されます。
プラグインによるパッケージ管理
LambdaはPython3.7で実行しました。 Lambda関数でrequestsパッケージを呼び出します。 パッケージ管理にserverless-python-requirementsプラグインを利用します。 serverlessのブログを参考にしました。プラグインとrequestモジュールをインストールします。
npm install --save serverless-python-requirements pip install requests pip freeze > requirements.txt
プラグインの実行にはDockerが必要です。 Dockerデーモンを起動しておきます。
providedテンプレートの作成
Serverless Frameworkの設定に移ります。以下のコマンドを実行すると、serverless.yml、handler.pyのテンプレートが作成されます。
serverless create -t aws-python3 -n guardduty2backlog
ファイルの記載
3つのファイルを作成します。
- serverless.yml(serverless frameworkの設定ファイル)
- handler.py(Lambda関数)
- sample-guardduty-event.json(テスト用のCloudWatchイベントファイル)
serverless.yml
Serverless Frameworkの設定ファイルです。 Lambda関数の設定、CloudWatch Events、GuardDutyの有効化、serverless-python-requirementsプラグインの設定を記載しています。environment
には、backlog設定で確認した内容を記載します。
service: guardduty2backlog provider: name: aws runtime: python3.7 # you can overwrite defaults here stage: prod region: ap-northeast-1 # you can add packaging information here package: exclude: - consolelogin.json functions: main: handler: handler.main events: - cloudwatchEvent: event: source: - "aws.guardduty" detail-type: - "GuardDuty Finding" # Define function environment variables here environment: api_key: '' # backlog's API Key space_key: '' # classmethod backlog space key project_id: '' # backlog project id issue_type_id: '' # backlog issue type id. priority_id: '3' # backlog priority. normal = 3 plugins: - serverless-python-requirements custom: pythonRequirements: dockerizePip: true resources: # CloudFormation template syntax Resources: GDD: Type: "AWS::GuardDuty::Detector" Properties: Enable: true
handler.py
Lambda関数です。GuardDutyのイベントの内容を変数に格納してから、POSTします。BASE_URLは環境によって、backlog.com
かbacklog.jp
を選びます。
# -*- coding: utf-8 -*- import requests import os BASE_URL = 'https://{space_key}.backlog.com/api/v2/{api}' # BASE_URL = 'https://{space_key}.backlog.jp/api/v2/{api}' api_key = os.environ['api_key'] space_key = os.environ['space_key'] def add_issue(_project_key, _issue_type_id, _priority_id, _summary, _description): api = 'issues' url = BASE_URL.format(space_key=space_key, api=api) payload={ 'projectId': _project_key, 'issueTypeId': _issue_type_id, 'priorityId': _priority_id, 'summary': _summary, 'description': _description } params = { 'apiKey': api_key, } r = requests.post(url, params=params, data=payload) r.raise_for_status() return r def main(event, context): project_id = os.environ['project_id'] issue_type_id = os.environ['issue_type_id'] priority_id = os.environ['priority_id'] summary = str(event['detail-type']) if 'detail' in event: if 'title' in event['detail']: summary += "(" + str(event['detail']['title']) + ")" description = "version:" + str(event['version']) + '\n' messages_keys = ["account","time","region","detail-type"] for key in messages_keys: description += key + ":" + str(event[key]) + '\n' messages_detail_keys = ["accountId","type","title","desctiption","account","region","createdAt","updatedAt"] for key in messages_detail_keys: if 'detail' in event: if key in event['detail']: description += key + ":" + str(event['detail'][key]) + '\n' add_issue(project_id, issue_type_id, priority_id, summary, description)
sample-guardduty-event.json
CloudWatchイベントのルールの作成からAWS コンソールのサインインを選択すると、サンプルイベントを表示できます。jsonが表示されるのでコピーアンドペーストしsample-guardduty-event.jsonを作成します。
デプロイ
デプロイコマンドを実行します。
sls deploy
サンプルイベントを使って、テストします。 backlog課題が作成されれば、成功です。
sls invoke -f main -p consolelogin.json
GuardDutyは全てのリージョンで有効にすることが推奨されます。他のリージョンについても、デプロイします。オレゴンリージョンへのデプロイは以下のように行います。
sls deploy --region us-west-2
backlog運用イメージ
GuardDutyのイベントが発生すると以下のように課題が作成されます。
担当者をアサインし確認します。イベントの調査内容を記載したら、完了にします。
動作テストで発生した課題はまとめてクローズできます。
さいごに
Amazon GuardDutyのイベントをbacklogに連携する方法をご紹介しました。GuardDutyでイベントが発生したら誤検知か確認する必要があります。backlogに連携することでステータスや担当者、対応内容を管理できます。
参考
検証環境
Mac OSで以下のバージョンで検証しました。
$ serverless -v Framework Core: 1.50.0 Plugin: 1.3.8 SDK: 2.1.0 $